package com.sjzd.menu;

import com.sjzd.ConfigParser;
import com.sjzd.entity.Bullet;
import com.sjzd.entity.Tank;
import com.sjzd.exception.NullObjectException;
import com.sjzd.message.TankStatusMessage;
import com.sjzd.net.ClientNet;

import java.util.*;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;

public class GameMenu {
    private List<Tank> otherTankList = new CopyOnWriteArrayList<>();
    private Map<String, Tank> otherTankMap = new ConcurrentHashMap<>(10);
    private List<Bullet> bulletList = new CopyOnWriteArrayList<>();
    private Tank tank = null;
    private ClientNet clientNet = null;
    private MainMenu mainMenu = null;
    private ConfigParser configParser = null;
    public GameMenu(String nickname, ClientNet clientNet) {
        this.clientNet = clientNet;
        configParser = ConfigParser.getInstance();
        tank = createSelfTank(nickname);
        tank.setTankStatusMessage(new TankStatusMessage(tank.getId(),
                tank.X, tank.Y, tank.sinX, tank.sinY, tank.isExist));
    }

    public ClientNet getClientNet() {
        return clientNet;
    }

    public void addTank(Tank other) throws NullObjectException {
        if (null == other) {
            throw new NullObjectException("传入的参数对象为空");
        }
        otherTankMap.put(other.getId(), other);
        otherTankList.add(other);
    }

    public void removeTank(String id) throws NullObjectException {
        if (null == id || ("").equals(id)) {
            throw new NullObjectException("传入的参数对象为空");
        }
        Tank removeTank = otherTankMap.remove(id);
        otherTankList.remove(removeTank);
    }

    public List<Tank> getOtherTankList() {
        return otherTankList;
    }

    public Tank getOtherTank(String id) throws NullObjectException {
        if (null == id || ("").equals(id)) {
            throw new NullObjectException("传入的参数对象为空");
        }
        return otherTankMap.get(id);
    }

    public void addBullet(Bullet bullet) throws NullObjectException {
       if (null == bullet) {
           throw new NullObjectException("传入的参数对象为空");
       }
        bulletList.add(bullet);
    }

    public void removeBullet(String id) throws NullObjectException {
       if (null == id || ("").equals(id)) {
           throw new NullObjectException("传入的参数对象为空");
       }
       for (Bullet bullet : bulletList) {
           if (bullet.getId().equals(id)) {
               bulletList.remove(bullet);
               return;
           }
       }
    }

    public Bullet getBullet(String id) throws NullObjectException {
        if (null == id || ("").equals(id)) {
            throw new NullObjectException("传入的参数对象为空");
        }
        for (Bullet bullet : bulletList) {
            if (bullet.getId().equals(id)) {
                return bullet;
            }
        }
        return null;
    }

    public List<Bullet> getBulletList() {
        return bulletList;
    }


    /**
     *  此方法只在客户端初始化完成后调用，而且仅调用一次
     * @param nickname
     * @return
     */
    private Tank createSelfTank(String nickname) {
        return new Tank(this, UUID.randomUUID().toString(),
                nickname,200,200, configParser.getTANK_SPEED());
    }

    /**
     *  此方法是在本地客户端发射炮弹后和其他网络客户端发来相关信心后调用
     *      注意： 本地客户端还需要设置所属tank的id
     * @param id
     * @param x
     * @param y
     * @param sinX
     * @param sinY
     * @return
     */
    public Bullet loadOtherBullet(String id, int x, int y, double sinX, double sinY) {
        return new Bullet(this, id, x, y, sinX, sinY, configParser.getBULLET_SPEED());
    }

    public Tank getTank() { return tank; }

    /**
     *  展示游戏界面
     *  当与服务器建立连接成功后，再调用此方法
     */
    public void showGame() {
        mainMenu = new MainMenu(this);
        onlineGreet();
        while (true) {
            mainMenu.repaint();
            try  {
                Thread.sleep(30);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     *  玩家上线后给其他玩家发送自己上线的信息
     */
    private void onlineGreet() {
        tank.publishMessage(tank.getTankStatusMessage());
    }
}
